package dao

import (
	"fmt"
	"math"
	"time"

	"user_srv/basic/config"
	"user_srv/handler/model"
)

// LBSService LBS（基于地理位置的服务）
// 负责用户位置的存储、更新和查询
// 提供附近的人、地理位置推荐等功能
type LBSService struct{}

// NewLBSService 创建LBS服务实例
// 确保表结构存在，如果不存在则创建
func NewLBSService() *LBSService {
	// 确保表结构存在
	err := model.InitTable()
	if err != nil {
		fmt.Printf("初始化表结构失败: %v\n", err)
	} else {
		fmt.Printf("表结构初始化成功\n")
	}
	return &LBSService{}
}

// UpdateLocation 更新用户位置
// 功能：更新或创建用户的实时地理位置信息
// 应用场景：
//   - 用户打开APP时自动更新位置
//   - 用户主动分享位置
//   - 用于"附近的人"功能
//
// 参数：
//   - userId: 用户ID
//   - latitude: 纬度（-90到90）
//   - longitude: 经度（-180到180）
//   - city: 城市名称
//   - address: 详细地址
func (s *LBSService) UpdateLocation(userId int64, latitude, longitude float64, city, address string) error {
	// 参数验证
	if userId <= 0 {
		return fmt.Errorf("用户ID无效")
	}
	if latitude < -90 || latitude > 90 {
		return fmt.Errorf("纬度无效")
	}
	if longitude < -180 || longitude > 180 {
		return fmt.Errorf("经度无效")
	}

	// 测试数据库连接
	sqlDB, err := config.DB.DB()
	if err != nil {
		fmt.Printf("获取数据库连接失败: %v\n", err)
		return fmt.Errorf("数据库连接失败: %v", err)
	}

	// 测试数据库连接
	err = sqlDB.Ping()
	if err != nil {
		fmt.Printf("数据库连接测试失败: %v\n", err)
		return fmt.Errorf("数据库连接测试失败: %v", err)
	}
	fmt.Printf("数据库连接正常\n")

	// 创建或更新位置记录
	location := &model.XqUserLocations{
		UserId:    userId,
		Latitude:  latitude,
		Longitude: longitude,
		City:      city,
		Address:   address,
	}

	// 添加调试信息
	fmt.Printf("正在更新用户位置: UserID=%d, Lat=%.6f, Lng=%.6f, City=%s, Address=%s\n", userId, latitude, longitude, city, address)

	err = location.Upsert()
	if err != nil {
		fmt.Printf("更新位置失败: %v\n", err)
		return err
	}

	fmt.Printf("位置更新成功: UserID=%d\n", userId)
	return nil
}

// GetNearbyUsers 获取附近的用户
// 功能：基于用户位置，查找附近的用户
// 算法：
//   - 使用Haversine公式计算地球表面两点间的精确距离
//   - 按距离从近到远排序
//   - 返回用户基本信息+距离+城市
//
// 参数：
//   - userId: 当前用户ID
//   - latitude: 当前纬度
//   - longitude: 当前经度
//   - radius: 搜索半径（公里，默认10）
//
// 返回值：附近用户列表，包含距离信息
func (s *LBSService) GetNearbyUsers(userId int64, latitude, longitude float64, radius int32) ([]*NearbyUserInfo, error) {
	// 参数验证
	if userId <= 0 {
		return nil, fmt.Errorf("用户ID无效")
	}
	if latitude < -90 || latitude > 90 {
		return nil, fmt.Errorf("纬度无效")
	}
	if longitude < -180 || longitude > 180 {
		return nil, fmt.Errorf("经度无效")
	}
	if radius <= 0 {
		radius = 10 // 默认10公里
	}

	// 获取附近的位置记录
	locations, err := model.GetUsersInRadius(userId, latitude, longitude, radius)
	if err != nil {
		return nil, fmt.Errorf("获取附近用户失败: %v", err)
	}

	// 转换为业务对象
	var users []*NearbyUserInfo
	for _, location := range locations {
		// 获取用户基本信息
		userProfile, err := s.getUserProfile(location.UserId)
		if err != nil {
			// 如果获取用户信息失败，跳过该用户
			continue
		}

		// 计算精确距离
		distance := HaversineDistance(latitude, longitude, location.Latitude, location.Longitude)

		user := &NearbyUserInfo{
			UserId:     location.UserId,
			Nickname:   userProfile.Nickname,
			Avatar:     userProfile.Avatar,
			Age:        userProfile.Age,
			Gender:     int32(userProfile.Gender),
			DistanceKm: distance,
			City:       location.City,
		}
		users = append(users, user)
	}

	return users, nil
}

// GetUserLocation 获取用户位置
// 功能：获取指定用户的最新位置信息
// 应用场景：
//   - 查看自己的位置信息
//   - 获取好友位置（需要授权）
//   - 显示用户在地图上的位置
//
// 参数：
//   - userId: 用户ID
//
// 返回值：用户位置信息（经纬度、城市、更新时间）
func (s *LBSService) GetUserLocation(userId int64) (*UserLocationInfo, error) {
	// 参数验证
	if userId <= 0 {
		return nil, fmt.Errorf("用户ID无效")
	}

	// 获取位置记录
	var location model.XqUserLocations
	err := location.GetByUserId(userId)
	if err != nil {
		return nil, fmt.Errorf("用户位置不存在")
	}

	// 转换为业务对象
	userLocation := &UserLocationInfo{
		UserId:    location.UserId,
		Latitude:  location.Latitude,
		Longitude: location.Longitude,
		City:      location.City,
		UpdatedAt: location.UpdatedAt,
	}

	return userLocation, nil
}

// getUserProfile 获取用户基本信息
func (s *LBSService) getUserProfile(userId int64) (*model.XqUserProfiles, error) {
	var profile model.XqUserProfiles
	err := config.DB.Where("user_id = ?", userId).First(&profile).Error
	if err != nil {
		return nil, err
	}
	return &profile, nil
}

// HaversineDistance 计算两点间距离（公里）
// 功能：使用Haversine公式计算地球表面两点间的精确距离
// 算法说明：
//   - Haversine是计算大圆距离的公式，适用于地球表面的距离计算
//   - 考虑了地球的曲率，计算结果更准确
//
// 参数：
//   - lat1, lon1: 起点经纬度
//   - lat2, lon2: 终点经纬度
//
// 返回值：两点间的距离（单位：公里）
func HaversineDistance(lat1, lon1, lat2, lon2 float64) float64 {
	const R = 6371 // 地球半径（公里）

	// 转换为弧度
	lat1Rad := lat1 * math.Pi / 180
	lon1Rad := lon1 * math.Pi / 180
	lat2Rad := lat2 * math.Pi / 180
	lon2Rad := lon2 * math.Pi / 180

	// Haversine公式
	dLat := lat2Rad - lat1Rad
	dLon := lon2Rad - lon1Rad
	// 计算距离
	a := math.Sin(dLat/2)*math.Sin(dLat/2) +
		math.Cos(lat1Rad)*math.Cos(lat2Rad)*
			math.Sin(dLon/2)*math.Sin(dLon/2)

	c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))

	return R * c
}

// NearbyUserInfo 附近用户信息结构体
// 用于返回附近用户的信息
// - UserId: 用户ID
// - Nickname: 昵称
// - Avatar: 头像URL
// - Age: 年龄
// - Gender: 性别
// - DistanceKm: 距离（公里）
// - City: 城市名称
type NearbyUserInfo struct {
	UserId     int64   `json:"user_id"`
	Nickname   string  `json:"nickname"`
	Avatar     string  `json:"avatar"`
	Age        int32   `json:"age"`
	Gender     int32   `json:"gender"`
	DistanceKm float64 `json:"distance_km"`
	City       string  `json:"city"`
}

// UserLocationInfo 用户位置信息结构体
// 用于返回用户的地理位置信息
// - UserId: 用户ID
// - Latitude: 纬度
// - Longitude: 经度
// - City: 城市名称
// - UpdatedAt: 位置更新时间
type UserLocationInfo struct {
	UserId    int64     `json:"user_id"`
	Latitude  float64   `json:"latitude"`
	Longitude float64   `json:"longitude"`
	City      string    `json:"city"`
	UpdatedAt time.Time `json:"updated_at"`
}
